package com.tanhua.app.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.api.db.UserInfoApi;
import com.tanhua.api.mongo.VideoApi;
import com.tanhua.app.interceptor.UserHolder;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.FollowUser;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageBeanVo;
import com.tanhua.domain.vo.VideoVo;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;

@Service
public class VideoService {

    @Reference
    private VideoApi videoApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 从reis中查询该用户推荐视频
    public PageBeanVo findRecommendByRedis(Integer pageNum, Integer pageSize) {
        PageBeanVo pageBeanVo = null;
        // 1、拼接key
        String key = "QUANZI_VIDEO_RECOMMEND_" + UserHolder.getUserId();
        // 2、获取redis中的value
        String value = stringRedisTemplate.opsForValue().get(key);

        if (StrUtil.isNotEmpty(value)) {
            // 3、模拟数据库计算分页
            String[] vids = value.split(",");// 10015,100092,18,20011,20,20,22,20009,20008,23....... 上百条
            // redis中没有分页功能，需要我们自己计算 起始值和结束值
            Integer startIndex = (pageNum - 1) * pageSize; // 起始值
            if (startIndex < vids.length) { //起始条数大于数据总数
                Integer endIndex = startIndex + pageSize - 1;
                if (endIndex >= vids.length) {
                    endIndex = vids.length - 1;
                }
                List<Long> vidList = new ArrayList<>();   //本页查询的所有小视频的vid列表
                for (int i = startIndex; i <= endIndex; i++) {
                    vidList.add(Long.valueOf(vids[i]));
                }

                // 4、封装分页对象
                List<Video> list = videoApi.findByVids(vidList);
                long counts = ((Integer) vids.length).longValue();
                pageBeanVo = new PageBeanVo(pageNum, pageSize, counts, list);
            }
        }

        return pageBeanVo;

    }

    // @Cacheable(value = "video", key = "#pageNum+'_'+#pageSize") // 课下作业解决bug
    public PageBeanVo findByPage(Integer pageNum, Integer pageSize) {  // 第一页  第二页  第三页

        // a、先查询redis
        PageBeanVo pageBeanVo = findRecommendByRedis(pageNum, pageSize);
        if (pageBeanVo == null) {
            // b、如果没有再查询默认数据
            pageBeanVo = videoApi.findByPage(pageNum, pageSize);
        }

        // 2、封装vo
        List<VideoVo> voList = new ArrayList<>();
        List<Video> videoList = (List<Video>) pageBeanVo.getItems();
        if (CollectionUtil.isNotEmpty(videoList)) {
            for (Video video : videoList) {
                VideoVo vo = new VideoVo();
                UserInfo userInfo = userInfoApi.findByUserId(video.getUserId());
                BeanUtil.copyProperties(userInfo, vo);
                BeanUtil.copyProperties(video, vo);
                vo.setCover(video.getPicUrl()); // 小视频封面
                vo.setSignature(video.getText()); // 小视频签名
                vo.setHasLiked(0); // 是否点赞

                if (stringRedisTemplate.hasKey(StrUtil.format("follow_user_{}_{}", UserHolder.getUserId(), video.getUserId()))) {
                    vo.setHasFocus(1); // 是否关注
                } else {
                    vo.setHasFocus(0); // 是否关注
                }

                vo.setId(video.getId().toHexString()); // 小视频id

                voList.add(vo);
            }
        }

        pageBeanVo.setItems(voList);
        return pageBeanVo;
    }

    @Autowired
    private VideoMqService videoMqService;

    // @CacheEvict(value = "video", allEntries = true)
    public ResponseEntity saveVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws Exception {
        // 1、封面上传到阿里云oss
        String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        // 2、小视频上传fastDFS
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), FileUtil.extName(videoFile.getOriginalFilename()), null);
        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();
        // 3、创建video对象
        Video video = new Video();
        video.setId(ObjectId.get()); // 添加，手动指定主键
        video.setUserId(UserHolder.getUserId()); // 发布人
        video.setPicUrl(picUrl); // 封面
        video.setVideoUrl(videoUrl); // 小视频
        video.setText("左右右手一个慢动作~~~"); // 文字
        // 4、保存
        videoApi.save(video);

        // 发送小视频mq的消息
        videoMqService.videoMsg(video.getId().toHexString());

        return ResponseEntity.ok(null);
    }

    public ResponseEntity userFocus(Long followUserId) {
        // 1、封装 FollowUser对象
        FollowUser followUser = new FollowUser();
        followUser.setUserId(UserHolder.getUserId()); // 登录人id
        followUser.setFollowUserId(followUserId); // 小视频用户id
        // 2、调用api保存
        videoApi.saveFollowUser(followUser);

        // 3、向redis中存储关注标记
        stringRedisTemplate.opsForValue().set(StrUtil.format("follow_user_{}_{}", UserHolder.getUserId(), followUserId), "1");

        return ResponseEntity.ok(null);
    }

    public ResponseEntity userUnFocus(Long followUserId) {
        // 1、调用api删除
        videoApi.removeFollowUser(UserHolder.getUserId(), followUserId);

        // 2、从redis中删除关注标记
        stringRedisTemplate.delete(StrUtil.format("follow_user_{}_{}", UserHolder.getUserId(), followUserId));
        return ResponseEntity.ok(null);
    }
}
